import { randomBytes } from '@stablelib/random'
import { generateKeyPairFromSeed, marshalPrivateKey, marshalPublicKey } from '@libp2p/crypto/keys'
import { peerIdFromKeys } from '@libp2p/peer-id'
import { peerIdFromString } from '@libp2p/peer-id'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import { unmarshalPublicKey } from '@libp2p/crypto/keys';

export function generateSeed() {
    return randomBytes(32);
}

export function seedToHex(seed) {
    return Buffer.from(seed).toString('hex');
}

export function seedHexToSeed(seedHex) {
    return new Uint8Array(Buffer.from(seedHex, 'hex'));
}

export const createEd25519PeerId = async (seed) => {
  const key = await generateKeyPairFromSeed('Ed25519', seed)
  const id = await createFromPrivKey(key)

  if (id.type === 'Ed25519') {
    return id
  }

  throw new Error(`Generated unexpected PeerId type "${id.type}"`)
}

async function createFromPrivKey (privateKey) {
    return await peerIdFromKeys(marshalPublicKey(privateKey.public), marshalPrivateKey(privateKey))
}

export const peerIdToDid = (peerId) => {
    const peer = peerIdFromString(peerId);
    return encodeDID(peer.publicKey)
}

function encodeDID(publicKey) {
    {/* @ts-ignore */}
    const pubKey = unmarshalPublicKey(publicKey)._key;
    const bytes = new Uint8Array(pubKey.length + 2);
    bytes[0] = 0xed; // ed25519 multicodec
    // The multicodec is encoded as a varint so we need to add this.
    // See js-multicodec for a general implementation
    bytes[1] = 0x01;
    bytes.set(pubKey, 2);
    return `did:key:z${uint8ArrayToString(bytes, 'base58btc')}`;
}
